package com.ch.common.net

import android.util.Log
import androidx.lifecycle.liveData
import com.ch.common.net.retrofit.ReplaceUrlCallFactory
import com.ch.common.utils.LogUtils
import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
import okhttp3.Request
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.lang.Exception
import java.lang.RuntimeException
import java.util.concurrent.TimeUnit
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine

/**
 * Author: chenhu
 * Time: 2021/9/16 9:13
 * Description do somethings
 */

object RetrofitManager {
    private const val TIME_OUT = 30.toLong()
    private const val BASE_URL = "https://www.wanandroid.com/"
    const val MOVIE_BASE_URL = "https://cdn.3dfan.3dv.cn/"
    private val okHttpClient: OkHttpClient = OkHttpClient.Builder()
        .connectTimeout(TIME_OUT, TimeUnit.SECONDS)
        .readTimeout(TIME_OUT, TimeUnit.SECONDS)
        .writeTimeout(TIME_OUT, TimeUnit.SECONDS)
        .addInterceptor(LoggingInterceptor())
        .build();
    private val mRetrofit: Retrofit = Retrofit.Builder()
        .baseUrl(BASE_URL)
        .callFactory(object : ReplaceUrlCallFactory(okHttpClient) {
            override fun getNewUrl(baseUrlName: String?, request: Request?): HttpUrl? {
                if (baseUrlName == MOVIE_BASE_URL) {
                    val oldUrl = request?.url.toString()
                    val newUrl = oldUrl?.replace(BASE_URL, MOVIE_BASE_URL)
                    return newUrl.toHttpUrl()
                }
                return null
            }
        })
        .addConverterFactory(GsonConverterFactory.create())
        .build();

    fun <T> createServiceApi(tClass: Class<T>): T {
        return mRetrofit.create(tClass)
    }

    inline fun <reified T> createMySelf() = T::class.java

    suspend fun <T> Call<T>.await(): T {
        return suspendCoroutine {
            enqueue(object : Callback<T> {
                override fun onFailure(call: Call<T>, t: Throwable) {
                    it.resumeWithException(t)
                }

                override fun onResponse(call: Call<T>, response: Response<T>) {
                    val body = response.body()
                    if (body != null) {
                        it.resume(body)
                    } else {
                        it.resumeWithException(RuntimeException("response is null"))
                    }
                }

            })
        }
    }

    /**
     * TODO 这个方法一定要实现liveData的observe方法才会执行,直接调用不会执行
     * */
    fun <T> launcherNetApi(context: CoroutineContext, block: suspend () -> Result<T>) =
        liveData<Result<T>>(context) {
            val result = try {
                block()
            } catch (e: Exception) {
                Result.failure<T>(e)
            }
            emit(result)
        }
}











